#ifndef __DRAWABLE__H
#define __DRAWABLE__H

#include <SDL.h>
#include "vector2f.h"
#include <iostream>

using std::cout; using std::endl;

#define STATE_LIVING    0
#define STATE_COLLIDING 1
#define STATE_EXPLODING 2

#define TYPE_STATIC  0
#define TYPE_DYNAMIC 1

// Drawable is an Abstract Base Class (ABC) that specifies the methods
// that derived classes may and must have.
class Drawable
{
	public:
		Drawable(const Vector2f& pos, const Vector2f& vel, const Vector2f& mxv) : 
			position(pos), position_old(pos-(vel*(1.0/200.0))), velocity(vel), maxVelocity(mxv),
			accel(Vector2f()), state(STATE_LIVING), collidable(true), type(TYPE_DYNAMIC),
			restitution(0.9), friction(0.9), mass(1), owner(NULL), collideWithDynamic(true),
			ignoreGravity(false) {}

		Drawable(const Drawable& s) : position(s.position), position_old(s.position_old),
			velocity(s.velocity), maxVelocity(s.maxVelocity), accel(s.accel), state(s.state),
			collidable(s.collidable), type(s.type), restitution(s.restitution), friction(s.friction),
			mass(s.mass), owner(s.owner), collideWithDynamic(s.collideWithDynamic),
			ignoreGravity(s.ignoreGravity) { }

		virtual ~Drawable() {}

		virtual void draw() const = 0;
		virtual void update(Uint32 ticks) = 0;

		float X() const { return position[0]; }
		void X(float x) { position[0] = x; }

		float Y() const { return position[1]; }
		void Y(float y) { position[1] = y; }

		float velocityX() const { return velocity[0]; }
		void velocityX(float vx) { velocity[0] = vx; }

		float velocityY() const { return velocity[1]; }
		void velocityY(float vy) { velocity[1] = vy; }
		const Vector2f& getPosition() const { return position; }
		const Vector2f& getPositionOld() const { return position_old; }
		const Vector2f& getVelocity() const { return velocity; }
		const Vector2f& getMaxVelocity() const { return maxVelocity; }
		const Vector2f& getAccel() const { return accel; }
		void setPositionOld(const Vector2f& pos) { position_old = pos; }
		void setPosition(const Vector2f& pos) { position = pos; }
		void setVelocity(const Vector2f& vel) { velocity = vel; }
		void setMaxVelocity(const Vector2f& vel) { maxVelocity = vel; }

		void setAccel(const Vector2f& a) { accel = a; }
		void setState(int val) {state = val;}
		bool isState(int val) {if(state == val) return true; return false;}
		bool isCollidable() {return collidable;}
		void setCollidable(bool val) {collidable=val;}
		void applyForce(const Vector2f &f) {accel += f;}
		void setType(int t) {type = t;}
		int getType() {return type;}
		float getRestitution() {return restitution;}
		void setRestitution(float c) {restitution = c;}
		float getFriction() {return friction;}
		void setFriction(float c) {friction = c;}
		float getMass() {return mass;}
		void setMass(float m) {mass = m;}
		bool canCollideWithDynamic() { return collideWithDynamic; }
		void setCollideWithDynamic(bool val) { collideWithDynamic = val; }
		bool isIgnoreGravity() { return ignoreGravity; }
		void setIgnoreGravity(bool val) { ignoreGravity = val; }

	private:
		Vector2f position;
		Vector2f position_old;
		Vector2f velocity;
		Vector2f maxVelocity;
		Vector2f accel;
		int state;
		bool collidable;
		int type;
		float restitution; // coefficient of restitution
		float friction; // coefficient of friction
		float mass;
		Drawable *owner;
		bool collideWithDynamic;
		bool ignoreGravity;

		Drawable(Drawable &);
		Drawable &operator=(const Drawable&);
};

#endif // !__DRAWABLE_H
